# -*- coding: utf-8 -*-

"""
语言管理模块，用于实现应用程序的多语言支持。

支持为控件的不同属性设置不同的文本值。例如，一个按钮可以同时设置text和toolTip属性，
每个属性可以有不同的文本。可以通过以下两种方式实现：

1. 使用通用文本键：所有属性使用相同的文本值
   例如："button_key": "按钮文本"，所有属性都会使用"按钮文本"这个值

2. 使用属性特定的文本键：为每个属性单独设置文本值
   例如："button_key_text": "按钮文本", "button_key_toolTip": "按钮提示"
   这样text属性会使用"按钮文本"，而toolTip属性会使用"按钮提示"

如果同时定义了通用文本键和属性特定的文本键，会优先使用属性特定的文本键。
"""
from PySide2.QtCore import QObject, Signal as pyqtSignal, QCoreApplication, QTranslator # 使用PySide2的Signal并重命名以兼容旧代码
from PySide2.QtWidgets import QWidget, QLabel, QPushButton, QComboBox, QLineEdit, QToolTip, QGroupBox, QCheckBox, QAction, QMenu
import json
from pathlib import Path
from typing import Dict, List, Optional, Union, Any, Callable

from gglobal import config
from gglobal import logger


class LanguageManager(QObject):
    """
    语言管理器，负责应用程序的语言切换功能。
    支持对标准控件和自定义控件的文本翻译。
    使用单例模式确保全局只有一个实例。
    """
    _instance = None
    _initialized = False
    
    # 定义语言切换信号
    language_changed = pyqtSignal(dict)
    
    # 控件属性映射，定义不同类型控件应该翻译的属性
    WIDGET_PROPERTY_MAP = {
        QLabel: ["text", "toolTip"],
        QPushButton: ["text", "toolTip"],
        QComboBox: ["toolTip"],  # ComboBox的items需要单独处理
        QLineEdit: ["placeholderText", "toolTip"],
        QGroupBox: ["title", "toolTip"],
        QCheckBox: ["text", "toolTip"],
        QAction: ["text", "toolTip"],
        QMenu: ["title", "toolTip"],
    }
    
    def __new__(cls, parent=None):
        if cls._instance is None:
            cls._instance = super(LanguageManager, cls).__new__(cls)
        return cls._instance
    
    def __init__(self, parent=None):
        if self._initialized:
            return
        super(LanguageManager, self).__init__(parent)
        # 初始化语言资源
        self._languages = self._load_languages_from_file()
        
        # 注册的控件列表，用于语言切换时批量更新
        self._registered_widgets = []
        
        # 设置当前语言，默认为中文
        self._current_language = config.get_param("current_language") or "zh_CN"

        logger.info(f"初始化语言管理器，当前语言：{self._current_language}")
        
        # 标记为已初始化
        self._initialized = True
    
    def _load_languages_from_file(self) -> dict:
        """
        从JSON文件加载语言资源
        
        返回:
            dict: 语言资源字典
        """
        try:
            # 获取JSON文件路径
            current_dir = Path(__file__).parent.parent.parent  # 回到项目根目录
            json_file_path = current_dir / "resource" / "languages" / "mooetool.json"
            
            if json_file_path.exists():
                with open(json_file_path, 'r', encoding='utf-8') as f:
                    languages = json.load(f)
                logger.info(f"成功从文件加载语言资源: {json_file_path}")
                return languages
            else:
                logger.warning(f"语言文件不存在: {json_file_path}，使用默认语言资源")
                return self._get_default_languages()
        except Exception as e:
            logger.error(f"加载语言文件失败: {e}，使用默认语言资源")
            return self._get_default_languages()
    
    def _get_default_languages(self) -> dict:
        """
        获取默认语言资源（备用方案）
        
        返回:
            dict: 默认语言资源字典
        """
        return {
            "zh_CN": {
                "name": "中文",
                "ui": {
                    "app_title": "MooeTool - 工具集",
                    "app_description": "专业的日常工具集"
                },
                "custom": {},
                "constants": {}
            },
            "en_US": {
                "name": "English",
                "ui": {
                    "app_title": "MooeTool - Toolkit",
                    "app_description": "Professional Daily Toolkit"
                },
                "custom": {},
                "constants": {}
            }
        }
    
    def get_current_language(self) -> str:
        """
        获取当前语言代码
        """
        return self._current_language
    
    def get_language_text(self) -> dict:
        """
        获取当前语言的文本资源
        """
        return self._languages.get(self._current_language, self._languages["zh_CN"])
    
    def get_text(self, key: str, default: str = "", category: str = "ui") -> Any:
        """
        获取指定键的文本，如果不存在则返回默认值
        
        参数:
            key: 文本键名
            default: 默认值
            category: 文本类别，可选值为 "ui"(标准控件), "custom"(自定义控件), "constants"(常量)
        """
        language_text = self.get_language_text()
        if category in language_text:
            return language_text[category].get(key, default)
        return default
        
    def get_constant(self, key: str, default: str = "") -> str:
        """
        获取常量文本，用于代码中的文本输出
        
        参数:
            key: 常量键名
            default: 默认值
        """
        return self.get_text(key, default, category="constants")
    
    def register_widget(self, widget: QWidget, text_key: str = None, property_name: Union[str, List[str]] = None, custom_setter: Callable = None):
        """
        注册控件以便在语言切换时自动更新
        
        参数:
            widget: 要注册的控件
            text_key: 语言资源中的键名，如果为None则使用widget.objectName()
            property_name: 要设置的属性名，如果为None则根据控件类型自动选择
                          可以是字符串或字符串列表，支持同时设置多个属性
            custom_setter: 自定义设置函数，接收(widget, value)两个参数
        """
        if text_key is None and widget.objectName():
            text_key = widget.objectName()
        
        if text_key:
            widget_info = {
                "widget": widget,
                "text_key": text_key,
                "property": property_name,
                "custom_setter": custom_setter
            }
            self._registered_widgets.append(widget_info)
            logger.debug(f"注册控件: {widget.__class__.__name__}, key: {text_key}")
            
            # 立即应用当前语言
            self._apply_language_to_widget(widget_info)
    
    def register_combo_box(self, combo_box: QComboBox, items_key: str):
        """
        注册下拉框及其选项文本
        
        参数:
            combo_box: 下拉框控件
            items_key: 语言资源中的键名，对应的值应该是一个字符串列表
        """
        def update_combo_items(widget, items):
            current_index = widget.currentIndex()
            widget.clear()
            widget.addItems(items)
            if current_index >= 0 and current_index < len(items):
                widget.setCurrentIndex(current_index)
        
        self.register_widget(combo_box, items_key, custom_setter=update_combo_items)
    
    def _apply_language_to_widget(self, widget_info: dict):
        """
        将语言应用到指定的控件
        """
        widget = widget_info["widget"]
        text_key = widget_info["text_key"]
        property_name = widget_info["property"]
        custom_setter = widget_info["custom_setter"]
        
        # 获取文本值（从ui或custom类别获取）
        category = "custom" if text_key in self.get_language_text().get("custom", {}) else "ui"
        
        # 如果有自定义设置函数，则使用它
        if custom_setter:
            value = self.get_text(text_key, category=category)
            if value == "":
                return
            custom_setter(widget, value)
            return
        
        # 如果指定了属性名，则设置该属性
        if property_name:
            # 处理多属性情况
            if isinstance(property_name, list):
                properties = property_name
            else:
                properties = [property_name]
                
            for prop in properties:
                # 尝试获取属性特定的文本键
                prop_text_key = f"{text_key}_{prop}"
                # 首先尝试获取属性特定的文本，如果不存在则使用通用文本
                prop_value = self.get_text(prop_text_key, "", category=category)
                if prop_value == "":
                    prop_value = self.get_text(text_key, "", category=category)
                
                if prop_value == "":
                    continue
                    
                # 特殊处理某些控件的属性设置
                if isinstance(widget, QAction) and prop == "text":
                    widget.setText(prop_value)
                elif isinstance(widget, QMenu) and prop == "title":
                    widget.setTitle(prop_value)
                elif hasattr(widget, f"set{prop[0].upper()}{prop[1:]}"): 
                    # 使用setter方法
                    setter = getattr(widget, f"set{prop[0].upper()}{prop[1:]}")
                    setter(prop_value)
                elif hasattr(widget, prop):
                    # 直接设置属性
                    setattr(widget, prop, prop_value)
            return
        
        # 根据控件类型自动选择属性
        widget_type = type(widget)
        for base_type, properties in self.WIDGET_PROPERTY_MAP.items():
            if isinstance(widget, base_type):
                for prop in properties:
                    # 尝试获取属性特定的文本键
                    prop_text_key = f"{text_key}_{prop}"
                    # 首先尝试获取属性特定的文本，如果不存在则使用通用文本
                    prop_value = self.get_text(prop_text_key, "", category=category)
                    if prop_value == "":
                        prop_value = self.get_text(text_key, "", category=category)
                    
                    if prop_value == "":
                        continue
                        
                    # 特殊处理某些控件的属性设置
                    if isinstance(widget, QAction) and prop == "text":
                        widget.setText(prop_value)
                        break
                    elif isinstance(widget, QMenu) and prop == "title":
                        widget.setTitle(prop_value)
                        break
                    else:
                        setter_name = f"set{prop[0].upper()}{prop[1:]}"
                        if hasattr(widget, setter_name):
                            setter = getattr(widget, setter_name)
                            setter(prop_value)
                            break
                break
    
    def update_all_widgets(self):
        """
        更新所有注册的控件的语言
        """
        for widget_info in self._registered_widgets:
            self._apply_language_to_widget(widget_info)
    

    def set_language(self, lang_code: str):
        """
        设置当前语言。

        参数:
            lang_code: 语言代码 (例如 "zh_CN", "en_US")
        """
        if lang_code in self._languages:
            if self._current_language != lang_code:
                self._current_language = lang_code
                config.set_param("current_language", self._current_language)
                current_language_text = self.get_language_text()
                self.update_all_widgets()
                self.language_changed.emit(current_language_text)
                logger.info(f"语言已切换为：{current_language_text['name']}")
            else:
                logger.debug(f"语言已经是 {lang_code}，无需切换。")
        else:
            logger.warning(f"不支持的语言代码: {lang_code}")

    def toggle_language(self):
        """
        切换语言，在中英文之间切换
        """
        # 切换语言
        if self._current_language == "zh_CN":
            self._current_language = "en_US"
        else:
            self._current_language = "zh_CN"
        
        # 保存当前语言设置
        config.set_param("current_language", self._current_language)
        
        # 获取当前语言文本
        current_language_text = self.get_language_text()
        
        # 更新所有注册的控件
        self.update_all_widgets()
        
        # 发送语言变更信号
        self.language_changed.emit(current_language_text)
        logger.info(f"语言已切换为：{current_language_text['name']}")
        
        return current_language_text
    
    @classmethod
    def get_instance(cls, parent=None):
        """
        获取LanguageManager的单例实例
        
        参数:
            parent: 父对象，仅在首次创建时使用
        
        返回:
            LanguageManager: 单例实例
        """
        if cls._instance is None:
             cls._instance = cls(parent)
        return cls._instance
        
        # 注意：实际使用时不需要调用此示例方法，这只是展示用法

        
    def usage_example(self):
        """
        使用示例，展示如何使用语言管理器的各种功能
        """
        # 1. 注册控件并设置单个属性
        label = QLabel()
        self.register_widget(label, "time_label")
        
        # 2. 注册控件并设置多个属性
        button = QPushButton()
        self.register_widget(button, "connect_button", ["text", "toolTip"])
        # 注意：对于多属性控件，可以在语言资源中定义属性特定的文本
        # 例如："connect_button_text": "连接", "connect_button_toolTip": "点击连接到车辆"
        
        # 3. 使用自定义设置函数
        def custom_text_setter(widget, value):
            widget.setText(f"** {value} **")
            widget.setStyleSheet("color: blue;")
        
        custom_label = QLabel()
        self.register_widget(custom_label, "status_label", custom_setter=custom_text_setter)
        
        # 4. 注册下拉框
        combo_box = QComboBox()
        self.register_combo_box(combo_box, "view_selector")
        
        # 5. 获取常量文本用于代码中的输出
        connected_text = self.get_constant("connected_status")
        logger.info(f"连接状态: {connected_text}")
        
        # 6. 获取不同类别的文本
        ui_text = self.get_text("window_title", category="ui")
        custom_text = self.get_text("connect_button", category="custom")
        constant_text = self.get_text("error_message", category="constants")
        
        # 7. 获取属性特定的文本
        # 如果定义了属性特定的文本键（如"button_text"和"button_toolTip"），
        # 系统会自动使用这些特定文本；如果没有定义，则使用通用文本
        text_for_text_prop = self.get_text("button_text", category="ui")
        text_for_tooltip_prop = self.get_text("button_toolTip", category="ui")
        
        logger.debug(f"UI文本: {ui_text}")
        logger.debug(f"自定义控件文本: {custom_text}")
        logger.debug(f"常量文本: {constant_text}")
        logger.debug(f"文本属性特定文本: {text_for_text_prop}")